<template>
  <DragResize
    class="check-option"
    :class="{ 'is-item-active': active, 'is-editing': editing }"
    :title="data.isSet ? '' : option.label"
    :data="dragData"
    :parent="false"
    :style="{ transform: `translate(${option.x}px, ${option.y}px) ` }"
    :draggable="data.isSet"
    v-show="!(data.isDone && !option.value)"
    @drag-start="dragStart"
    @dragging="dragging"
    @drag-stop="dragStop"
    @mouseenter.native="hovering = true"
    @mouseleave.native="hovering = false"
    @click="onClick"
    @click.native.stop
  >
    <ElCheckbox
      :class="{ 'is-radio': isRadio, 'is-readonly': isReadonly }"
      :disabled="isReadonly"
      v-model="option.value"
      @change="$emit('change', option)"
    />

    <Transition v-if="removable" name="fa-widget__fade">
      <a
        v-show="hovering"
        class="fa-widget__close el-icon-error"
        @click.stop="$emit('remove', option)"
        @mousedown.stop
      ></a>
    </Transition>

    <Transition v-if="data.isSet" name="fa-widget__fade">
      <div v-show="active" @mousedown.stop>
        <input
          v-if="editing"
          ref="input"
          v-model.trim="option.label"
          class="check-option__input"
          :style="{ width: `${option.label.length + 1}em` }"
          :maxlength="maxLength"
          @blur="editing = false"
          @keyup.esc="editing = false"
          @keyup.enter="editing = false"
        />

        <div v-else class="check-option__label">
          <div class="check-option__label-text" :title="option.label">{{ option.label }}</div>

          <a class="check-option__label-edit fa-icon-edit" @click.stop="editing = true"></a>
        </div>
      </div>
    </Transition>
  </DragResize>
</template>

<script lang="ts">
import { computed, defineComponent, inject, nextTick, onMounted, ref, watch } from 'vue'
import config from '@/config'
import { MovingData, Viewer } from '@/types'
import { Widget, CheckOption } from '@/models'
import DragResize from '@/components/drag-resize/DragResize.vue'

/** 单、复选框 项目 */
export default defineComponent({
  name: 'FaWidgetCheckOption',

  props: {
    /** 控件数据 */
    data: {
      type: Widget,
      required: true
    },

    /** 当前选项 */
    option: {
      type: CheckOption,
      required: true
    },

    /** 是否激活 */
    active: {
      type: Boolean,
      default: false
    },

    /** 是否可删除 */
    removable: {
      type: Boolean,
      default: true
    },

    /** 是否单选 */
    isRadio: {
      type: Boolean,
      default: true
    },

    /** 是否只读 */
    isReadonly: {
      type: Boolean,
      default: true
    }
  },

  emits: [
    /** 选项值改变 `change(option: CheckOption)` */
    'change',

    /** 选项被移除 `remove(option: CheckOption)` */
    'remove'
  ],

  components: { DragResize },

  setup(props, { emit }) {
    /** 合同控件 */
    const viewer = inject('Viewer') as Viewer

    /** 编辑输入框 */
    const input = ref(null as null | HTMLInputElement)

    /** 编辑中 */
    const editing = ref(false)

    /** 选项配置 */
    const optionConfig = config.checkOption

    /** 范围 */
    const range = computed(() => {
      const { space } = optionConfig
      const { w, h } = props.option
      const { w: pw, h: ph } = props.data.page || { w: Infinity, h: Infinity }

      return { minX: space, maxX: pw - space - w, minY: space, maxY: ph - space - h }
    })

    /** 适应范围 */
    function adjust() {
      const { option } = props
      let { x, y } = option
      const { minX, maxX, minY, maxY } = range.value

      if (x < minX) x = minX
      if (x > maxX) x = maxX
      if (y < minY) y = minY
      if (y > maxY) y = maxY

      Object.assign(option, { x, y })
    }

    onMounted(adjust)

    /** 开始编辑后聚焦输入框 */
    watch(editing, async val => {
      if (val) {
        await nextTick()
        input.value?.focus()
      }
    })

    return {
      /** 鼠标悬浮 */
      hovering: ref(false),

      /** 编辑输入框 */
      input,

      /** 编辑中 */
      editing,

      /** 最大长度 */
      maxLength: optionConfig.maxLength,

      /** 拖拽数据 */
      dragData: computed(() => {
        const { x, y, w, h } = props.option
        return {
          x,
          y,
          w,
          h,
          zoom: viewer.zoom.level
        }
      }),

      /** 拖拽开始 */
      dragStart(e: MouseEvent) {
        const widget = props.data

        if (e.ctrlKey || e.metaKey) {
          // Ctrl/Cmd 点击添加多选
          viewer.selection.add(widget)
          return
        }

        // 设置控件激活并清除多选
        viewer.activeWidget = widget
        viewer.selection.clear()
      },

      /** 拖拽时同步位置 */
      dragging(e: MouseEvent, { x, y }: MovingData) {
        Object.assign(props.option, { x, y })
        adjust()
      },

      /** 拖拽结束 */
      dragStop() {
        viewer.updateSortedWidgets()
      },

      /** 点击 */
      onClick(e: MouseEvent) {
        viewer.$emit('widget-click', props.data, e)
        viewer.$emit('widgets-click', [props.data], e)
      }
    }
  }
})
</script>

<style lang="scss">
.fa-widget-check-group {
  .fa-widget {
    &.widget-mode-set ~ .check-option {
      .el-checkbox__input.is-disabled .el-checkbox__inner {
        cursor: move;
      }
    }

    &.widget-mode-done ~ .check-option::before {
      display: none;
    }
  }

  .check-option {
    position: absolute;
    z-index: 4;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;

    &:hover {
      z-index: 6;
    }

    &.is-item-active {
      z-index: 5;
    }

    &::before {
      position: absolute;
      top: -50%;
      left: -50%;
      box-sizing: border-box;
      width: 200%;
      height: 200%;
      border: 0.5px dashed rgba($color-primary, 0.4);
      border-radius: 2px;
      content: '';
    }

    &:hover::before,
    &.is-item-active::before {
      border-style: solid;
    }

    .el-checkbox {
      line-height: 1;
    }

    .fa-widget__close {
      margin: 0 0 2px -1px;
    }

    &.is-dragging {
      .check-option__label,
      .fa-widget__close {
        display: none;
      }
    }

    &__input,
    &__label {
      position: absolute;
      top: 150%;
      left: 50%;
      height: 24px;
      transform: translate(-50%, 4px);
    }

    &__input {
      min-width: 80px;
      max-width: 180px;
      padding: 0;
      font-size: 12px;
      text-align: center;
      border: 1px solid $color-primary;
      border-radius: 2px;

      &:focus {
        border-color: $color-primary;
      }

      &:focus-visible {
        outline: none;
      }
    }

    &__label {
      display: flex;
      align-items: center;
      padding: 0 12px;
      font-size: 12px;
      background: $background-color-secondary;
      border: 1px solid $border-color;
      border-radius: 2px;
      cursor: default;

      &-text {
        flex: auto;
        max-width: 160px;
        height: 100%;
        line-height: 24px;
        @include text-ellipsis();
      }

      &-edit {
        flex: none;
        margin-left: 6px;
        font-size: 14px;
        cursor: pointer;

        &:hover {
          color: $color-primary;
        }
      }
    }
  }

  /** 填写时默认出现外框 */
  &.widget-mode-use {
    .check-option::before {
      display: block;
    }
  }

  // 参与方颜色样式
  @each $c, $color in $actor-colors {
    .actor-#{$c} ~ .check-option {
      &::before {
        background: rgba($color, 0.03);
        border-color: rgba($color, 0.4);
      }

      &:hover::before,
      &.is-item-active::before {
        border-color: rgba($color, 0.8);
      }

      @include setCheckboxColor($color);
    }
  }
}
</style>
